﻿using System;
using System.Linq;
using System.Linq.Expressions;
using System.Reflection;
using System.Collections.Generic;
using Common.DataTypes;
using System.Threading;

namespace LinqAmazonProvider
{
    public class AmazonProvider : IQueryProvider 
    {
        public string AmazonKey { get; set; }
        public string ResultLanguage { get; set; }
     
        //Constructor
        public AmazonProvider()
        {     
        }
           
        #region IQueryProvider Members

        public IQueryable<TElement> CreateQuery<TElement>(Expression expression)
        {
            return new AmazonQuery<TElement>(this, expression);
        }

        public IQueryable CreateQuery(Expression expression)
        {
            Type elementType = TypeSystem.GetElementType(expression.Type);
            try
            {
                // Creation of the IQueryable by reflection
                return (IQueryable)Activator.CreateInstance(typeof(AmazonQuery<>).MakeGenericType(elementType), new object[] { this, expression });
            }
            catch (TargetInvocationException tie)
            {
                throw tie.InnerException;
            }
        }

     
        public TResult Execute<TResult>(Expression expression)
        {
            //string executeResult = (string)Execute(expression);
            //TResult result = ResultXMLParser<TResult>.Parse(executeResult);

            return (TResult)Execute(expression);
        }

        private static Dictionary<string, string> GetParams(Expression expression)
        {
            
            Dictionary<string,string> parameters;
            
            // Retrieve criteria
            parameters = new AmazonExpressionVisitor().ProcessExpression(expression);   //(Expression.Constant(fn.DynamicInvoke(null), expression.Type)));//.Value as IQueryable).Expression);
            return (parameters);
        }

        //This method execute the search with the parmeters from the query.

        public object Execute(Expression expression)
        {            
            Dictionary<string, string> parameters = GetParams(expression);
            AmazonSearch amazonSearch = new AmazonSearch();

            // Set language to load the right image when image not found, and the Amazon key to perform the search
            parameters.Add("Language", this.ResultLanguage);
            parameters.Add("AWSAccessKeyId", this.AmazonKey);

            return (object)(ResultXmlParser.GetQueryResult(amazonSearch.PerformWebServiceSearch(parameters).ToList<string>(), parameters));
        }

        #endregion
    }
}
